// Copyright 2011 Jay Young. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview
 *
 * Command object for retrieving posts from the server.
 */

goog.provide('rb.post.GetPostCommand');
goog.provide('rb.post.GetPostCommand.FailureCode');

goog.require('relief.rpc.Command');



/**
 * A Command object for retrieving a single post from the server, given its
 * unique slug.
 *
 * @param {function(rb.post.BlogPost)} onSuccess The callback to execute with
 *    the requested blog post.
 * @param {function(rb.post.GetPostCommand.FailureCode)} onFailure The function
 *    to call if the server fails to return a blog post.
 * @param {string=} slug The slug of the post to request.  If not specified,
 *    the command retrieves the most recently posted blog entry.
 *
 * @constructor
 * @extends {relief.rpc.Command}
 */
rb.post.GetPostCommand = function(onSuccess, onFailure, slug) {
  var url = '/api/post/get' + (slug ? '/' + slug : '');
  goog.base(this, onSuccess, onFailure, 'Get:' + url + goog.now(),
            url, 'GET');

  /**
   * @type {string|undefined}
   * @private
   */
  this.slug_ = slug;

  /**
   * @type {rb.post.BlogPost}
   * @private
   */
  this.post_ = null;

  this.readFromCache = this.writeToCache = true;
};
goog.inherits(rb.post.GetPostCommand, relief.rpc.Command);


/**
 * Enum of reasons the request may have failed.  This is passed to the client's
 * onFailure method.
 *
 * @enum {number}
 */
rb.post.GetPostCommand.FailureCode = {
  /**
   * Request failed for some reason.  No content could be retrieved.
   */
  REQUEST_FAILED: 1,

  /**
   * Request was successful, but no post was found. This is returned when no
   * slug is provided and a "get latest post" request turns up empty, meaning
   * that no posts have yet been created.
   */
  NO_POSTS: 0
};


/**
 * @inheritDoc
 */
rb.post.GetPostCommand.prototype.onSuccess = function(event) {
  var status = event.target.getStatus();

  if (status === 200) {
    var response = /** @type {rb.post.BlogPost.ServerResponse} */
                   (event.target.getResponseJson()),
        post = rb.post.BlogPost.fromServerResponse(response);

    this.slug_ = post.getSlug();
    this.post_ = post;
    this.callersOnSuccess(post);
  }
  else if (status === 204) { // HTTP 204 No Content
    // This was a "get latest" command, and no posts have yet been created.
    this.callersOnFailure(rb.post.GetPostCommand.FailureCode.NO_POSTS);
  }
  else {
    this.callersOnFailure(rb.post.GetPostCommand.FailureCode.REQUEST_FAILED);
  }
};


/**
 * @inheritDoc
 */
rb.post.GetPostCommand.prototype.onFailure = function(event) {
  this.callersOnFailure(rb.post.GetPostCommand.FailureCode.REQUEST_FAILED);
};


/**
 * @return {Array.<string>} The cache key for the post with the requested slug.
 * @override
 */
rb.post.GetPostCommand.prototype.getCacheKeys = function() {
  var slug = this.slug_;
  if (slug) {
    return [
      rb.post.BlogPost.getCacheKey(slug)
    ];
  }
  else {
    return [];
  }
};


/**
 * @inheritDoc
 */
rb.post.GetPostCommand.prototype.getCacheValues = function() {
  var post = this.post_;

  if (post) {
    return [{
      key: post.getCacheKey(),
      value: post
    }];
  }
  else {
    return [];
  }
};


/**
 * @inheritDoc
 */
rb.post.GetPostCommand.prototype.onCacheHit = function(cached) {
  var post = /** @type {rb.post.BlogPost} */ (cached[0].value);
  this.callersOnSuccess(post);
};


/**
 * @inheritDoc
 */
rb.post.GetPostCommand.prototype.disposeInternal = function() {
  goog.base(this, 'disposeInternal');
  this.post_ = null;
};
